package Day_0224.NetWork;

/**
 * @author zxc
 * @date 2023/02/24 11:17
 **/
public class TCP_Sticking_Unpacking {
    public static void main(String[] args) {
        /**
         * TCP粘包、拆包及解决办法
         * ===》
         * 1.为什么常说 TCP 有粘包和拆包的问题而不说 UDP ？
         * （1）UDP 是基于报文发送的，UDP首部采用了 16bit 来指示 UDP 数据报文的长度，
         *  ===》
         *  在应用层能很好的将不同的数据报文区分开，从而避免粘包和拆包的问题。
         *
         * （2）TCP 是基于字节流的，虽然应用层和 TCP 传输层之间的数据交互是大小不等的数据块，
         *  但是 TCP 并没有把这些数据块区分边界，仅仅是一连串没有结构的字节流；
         *  另外从 TCP 的帧结构也可以看出，在TCP 的首部没有表示数据长度的字段，
         *  基于上面两点，在使用 TCP 传输数据时，才有粘包或者拆包现象发生的可能。
         *
         * ===》
         * 总结 ：
         * （1）TCP协议是基于字节流的协议 && 在TCP首部并没有指示数据长度;
         * （2）UDP协议是基于数据报文的协议 && UDP首部指定 UDP数据报文的长度;
         *
         * 2.为什么会发生TCP粘包和拆包
         * ===》
         * 1）拆包 ：
         * ===》
         * 即，所要发送的数据超过了 TCP发送缓冲区剩余空间大小/TCP发送缓冲区大小，则所要发送的数据不得不在发送前，对其进行拆包操作;
         * （1）要发送的数据大于 TCP 发送缓冲区剩余空间大小，将会发生拆包。
         * （2）待发送数据大于 MSS（最大报文长度），TCP 在传输前将进行拆包。
         *
         * 2）粘包 ：
         * ===>
         * 由于TCP发送数据的前提是 将发送缓冲区填满数据后，对其进行发送，由于最后一个数据包大小 > TCP发送缓冲区大小
         * 所以会导致对于最后一个数据包进行拆包，同时与前面数据进行粘连;
         * （1）要发送的数据小于 TCP 发送缓冲区的大小，TCP 将多次写入缓冲区的数据一次发送出去，将会发生粘包。
         * （2）接收数据端的应用层没有及时读取接收缓冲区中的数据，将发生粘包。
         *
         * 3.粘包、拆包解决办法
         * 1）由于 TCP 本身是面向字节流的，无法理解上层的业务数据，
         * 所以在底层是无法保证数据包不被拆分和重组的，这个问题只能通过上层的应用协议栈设计来解决，
         *
         * 2）根据业界的主流协议的解决方案，归纳如下：
         * （1）消息定长：
         *  发送端将每个数据包封装为固定长度（不够的可以通过补 0 填充），
         *  这样接收端每次接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
         *  ===》
         *  即，对于每一个所要发送的数据包规定为 固定长度，若是不够的话，则补0填充;
         *
         * （2）设置消息边界：
         *  服务端从网络流中按消息边界分离出消息内容。在包尾增加回车换行符进行分割，例如 FTP 协议。
         *
         * （3）将消息分为消息头和消息体：
         *  消息头中包含表示消息总长度（或者消息体长度）的字段。
         *
         * （4）更复杂的应用层协议比如 Netty 中实现的一些协议都对粘包、拆包做了很好的处理。
         *
         */
    }
}
